import os
import requests
from datetime import datetime, timedelta
import re
import shutil
import pandas as pd

GROUP_NAME = {"数学群", "语文群", "英语群"}   # 例：微信群名称
SAVE_DIR = ".\\WeChatTextExport"  # 导出目录，可自行修改

def is_url(s: str) -> bool:
    pattern = re.compile(
        r'^(https?://)'              # http:// or https://
        r'(([A-Za-z0-9-]+\.)+[A-Za-z]{2,})'  # domain
        r'(:\d+)?'                   # optional port
        r'(/[\w\d\-./?%&=]*)*$',     # path/query
        re.IGNORECASE
    )
    return re.match(pattern, s.strip()) is not None

class Downloader:
    def __init__(self, name: str, excel_file: str, url: str):
        self.name = name
        self.excel_file = excel_file
        self.url = url

    def ask_overwrite(self):
        if os.path.exists(self.excel_file):
            resp = input(f"⚠️ 文件 {self.excel_file} 已存在，是否覆盖？(y/n，默认是y)：").strip().lower()
            if resp == "":
                resp = "y"   # 用户直接回车时，默认设为 y
            if resp != "y":
                return False

            # 备份
            backup_path = self.excel_file + ".bak"
            # 如果已有旧的 .bak 就先删掉
            if os.path.exists(backup_path):
                os.remove(backup_path)
            shutil.move(self.excel_file, backup_path)
            print(f"已备份原文件为: {backup_path}")            

        return True

    def html_table_to_excel(self) -> bool:
        try:
            resp = requests.get(self.url, timeout=20)
            resp.raise_for_status()

            # 从 HTML 里自动抓表格
            tables = pd.read_html(resp.text)
            if not tables:
                print("网页中未发现表格")
                return False

            # 简单起见，只取第一个表
            df = tables[0]
            df.to_excel(self.excel_file, index=False)
            print(f"已将网页表格转换为 Excel：{self.excel_file}")
            return True

        except Exception as e:
            print("转换为 Excel 失败：", e)
            return False

    def download_tencent_doc(self) -> bool:
        """
        从腾讯文档下载内容：
        - 先判断远程是否存在
        - 再下载
        - 根据 Content-Type 自动选择扩展名
        :param url: 文档 URL
        :param save_path: 期望的保存“基础路径”，可不带扩展名
        :return: True = 成功下载并保存；False = 失败
        """
        headers = {
            "User-Agent": "Mozilla/5.0"
        }

        try:
            # 1. 先用 HEAD 判断一下能不能访问
            head_resp = requests.head(self.url, headers=headers, allow_redirects=True, timeout=10)
            if not (200 <= head_resp.status_code < 400):
                print(f"文件不存在或无法访问：HTTP {head_resp.status_code}")
                return False

            # 2. 开始正式下载
            resp = requests.get(self.url, headers=headers, stream=True, timeout=20)
            if resp.status_code != 200:
                print(f"下载失败：HTTP {resp.status_code}")
                return False

            # 3. 根据 Content-Type 判断格式
            content_type = resp.headers.get("Content-Type", "").lower()
            print("Content-Type:", content_type)

            # 默认使用调用者传入的后缀，如果没写后缀再根据类型补
            base, ext = os.path.splitext(self.excel_file)

            if ext == "":  # 调用方没写扩展名，我们帮他猜一下
                if "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" in content_type:
                    ext = ".xlsx"
                elif "text/html" in content_type:
                    ext = ".html"
                else:
                    # 其他类型你可以自己再加判断
                    ext = ".bin"  # 兜底：二进制

            real_save_path = base + ext

            # 4. 读取内容并安全写入
            data = resp.content
            with open(self.excel_file, "wb") as f:
                f.write(data)

            print(f"已写入新文件: {self.excel_file}")
            return True
        except Exception as e:
            print("下载时发生错误：", e)
            return False

class DownloaderFactory:
    def create_downloader(self, downloadername: str, url: str, target_date: datetime = None) -> Downloader:
        if target_date is None:
            target_date = datetime.today()

        yesterday = target_date - timedelta(days=1)
        # 自动生成文件路径
        excel_file = os.path.join(SAVE_DIR, f"{downloadername}_{target_date.strftime("%m%d")}.xlsx")
        
        # 打印检查信息
        print(f"📙 下载 Excel 文件: {excel_file}")

        if downloadername == "英语群":
            return Downloader(downloadername, excel_file, url)
        elif downloadername == "数学群":        
            return Downloader(downloadername, excel_file, url)
        elif downloadername == "语文群":
            return Downloader(downloadername, excel_file, url)
        else:
            raise ValueError("不认识的群名称")
        

def main():
    # 用户输入完整日期
    before_yesterday_date = datetime.today() - timedelta(days=2) # 与其它文件不同的是，如果要下载，默认下载前天的
    date_str = input(f"请输入要生成的日期（格式 yyyy-mm-dd 或 yyyy/mm/dd，例如 {before_yesterday_date.strftime("%Y-%m-%d")}）：").strip()

    # 兼容不同日期格式
    date_formats = ["%Y-%m-%d", "%Y/%m/%d", "%Y%m%d"]
    target_date = None
    for fmt in date_formats:
        try:
            target_date = datetime.strptime(date_str, fmt)
            break
        except ValueError:
            continue

    if target_date is None:
        print("❌ 无法识别输入的日期格式，使用默认日期")
        # target_date = datetime.today()
        target_date = before_yesterday_date

    factory = DownloaderFactory()
    for name in GROUP_NAME:
        resp = input(f"要下载{name}吗？如果想下载，直接输入URL，否则不下载：").strip().lower()
        if not is_url(resp):
            continue
        downloader = factory.create_downloader(name, resp, target_date)

        if not downloader.ask_overwrite():
            continue

        result = downloader.html_table_to_excel()
        print("下载结果：", result)


if __name__ == "__main__":
    main()